/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.mobiubiq.directory.service;

import org.mobiubiq.directory.service.handlers.FindServicesResponseHandler;
import org.mobiubiq.directory.client.*;
//import com.sun.midp.io.Base64;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.midlet.MIDlet;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.net.URLCodec;
import org.mobiubiq.directory.client.data.Service;
import org.mobiubiq.directory.client.object.AbstractObject;
import org.mobiubiq.directory.client.object.BarcodeObject;
import org.mobiubiq.directory.client.object.LocationObject;
import org.mobiubiq.directory.client.object.ObjectType;
import org.mobiubiq.directory.client.object.TagObject;
import org.mobiubiq.directory.client.object.io.JSONWriter;
import org.xml.sax.SAXException;

public class DirectoryService implements DirectoryServiceDao {

    private String blogthispost;
    private String blogthis;
    private String bookmarkthis;
    private String bookmarkthispost;
    private final String endpoint;
    private static DirectoryService instance;

    public static DirectoryService getInstance(MIDlet midlet) {
        if (instance == null) {
            synchronized (midlet) {
                if (instance == null) {
                    instance = new DirectoryService(midlet.getAppProperty(Constants.APP_PROPERTY_ENDPOINT));
                    instance.blogthis = midlet.getAppProperty(Constants.APP_PROPERTY_BLOGTHIS);
                    instance.blogthispost = midlet.getAppProperty(Constants.APP_PROPERTY_BLOGTHIS_POST);
                    instance.bookmarkthis = midlet.getAppProperty(Constants.APP_PROPERTY_BOOKMARKTHIS);
                    instance.bookmarkthispost = midlet.getAppProperty(Constants.APP_PROPERTY_BOOKMARKTHIS_POST);
                }
            }
        }
        return instance;
    }

    /**
     * 
     * @param endpoint
     */
    private DirectoryService(final String endpoint) {
        super();
        this.endpoint = endpoint;
    }
    /*
    public BlogEntry[] getBlogEntries(final String id, final int page) throws ServiceException {
    BlogEntry[] result = null;
    HttpConnection con = null;
    InputStream stream = null;
    try {
    String url = endpoint + blogthis + "?id=" + id + "&page=" + page;
    con = (HttpConnection) Connector.open(url);
    con.setRequestProperty("User-Agent", Constants.USER_AGENT);
    con.setRequestMethod(HttpConnection.GET);
    int rc = con.getResponseCode();
    if(rc != HttpConnection.HTTP_OK) {
    throw new IOException("HTTP Response Code:\t" + rc);
    }
    //            StringBuffer sb = new StringBuffer();
    //            InputStreamReader reader = new InputStreamReader(con.openInputStream());
    //            int c = -1;
    //            while((c = reader.read()) != -1) {
    //                sb.append((char)c);
    //            }
    //            System.out.println(sb.toString());
    stream = con.openInputStream();
    BlogEntriesResponseHandler handler = 
    new BlogEntriesResponseHandler(new Identifiable() {
    public String getId() {
    return id;
    }
    });
    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser parser = factory.newSAXParser();
    parser.parse(stream, handler);
    
    Vector entries = handler.getEntries();
    result = new BlogEntry[entries.size()];
    for(int i = 0; i < entries.size(); i++) {
    result[i] = (BlogEntry) entries.elementAt(i);
    }
    } catch (ParserConfigurationException e) {
    throw new ServiceException(e.getMessage());
    } catch (SAXException e) {   
    throw new ServiceException(e.getMessage());
    } catch (IOException e) {
    throw new ServiceException(e.getMessage());
    } finally {
    if(con != null) {
    try {con.close();} catch (IOException ex) {}
    con = null;
    }
    if(stream != null) {
    try {stream.close();} catch (IOException ex) {}
    stream = null;                
    }
    }
    return result;
    }
    
    public String getEndpoint() {
    return this.endpoint;
    }
    
    /**
     * 
     * @param input
     */

    public Vector findServices(AbstractObject object) throws ServiceException, NoServicesFoundException {
        Vector services = new Vector();

        //	build url
        HttpConnection con = null;
        try {
            URLCodec codec = new URLCodec();
            JSONWriter writer = new JSONWriter();
            //URLWriter writer = URLWriterFactory.get(object.getType());
            StringBuffer url = new StringBuffer(endpoint + Constants.OBJECTSERVICE);

            url.append("?");
            url.append("xml=1&");
            if (object instanceof LocationObject) {
                url.append("location=");
            } else if (object instanceof TagObject) {
                url.append("tag=");
            } else if (object instanceof BarcodeObject) {
                url.append("barcode=");
            }
            url.append(new String(codec.encode(writer.write(object).getBytes())));

            //	connect to directory service
            String sUrl = url.toString();
            con = (HttpConnection) Connector.open(sUrl);	//"http://localhost:8080/service-directory/service/");
            // needed for asp.net to accept request
            //con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13");
            int rc = con.getResponseCode();
            if (rc != HttpConnection.HTTP_OK) {
                throw new IOException("HTTP response code: " + rc);
            }
            InputStream stream = con.openInputStream();

            FindServicesResponseHandler handler = new FindServicesResponseHandler(object);
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            parser.parse(stream, handler);

            services = handler.getServices();//http://sdir.mobi/BookmarkThis.aspx?Page=1&IMSI=21
            addStandardServices(object, services);
//            if (services.size() > 0) {
//                this.fireServicesDetected(services);
//            }
//            if(services.size() == 0) {
//                throw new NoServicesFoundException();
//            }
            con.close();
            con = null;
            return services;
        } catch (ParserConfigurationException e) {
            throw new ServiceException(e.getMessage());
        } catch (SAXException e) {
            throw new ServiceException(e.getMessage());
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            if (con != null) {
                try {
                    con.close();
                } catch (IOException e) {
                    KuixClient.debug(e.getMessage());
                }
                con = null;
            }
        }
    }

    public void setOrUpdateTitle(AbstractObject object, String title, String description) throws ServiceException {
        HttpConnection conn = null;
        try {
            URLCodec codec = new URLCodec();
            StringBuffer url = new StringBuffer(endpoint + Constants.OBJECTSERVICE + Constants.DESCRIPTION);
            url.append("?");
            url.append("objectid=" + codec.encode(object.getObjectId()));
            url.append("&title=" + codec.encode(title));
            url.append("&description=" + codec.encode(description));

            conn = (HttpConnection) Connector.open(url.toString());
            if (conn.getResponseCode() != HttpConnection.HTTP_OK && conn.getResponseCode() != HttpConnection.HTTP_NO_CONTENT) {
                throw new ServiceException("HTTP response code: " + conn.getResponseCode());
            }
        } catch (IOException ex) {
            throw new ServiceException(ex.getMessage());
        } catch (EncoderException ex) {
            throw new ServiceException(ex.getMessage());            
        } finally {
            if(conn != null) {
                try {
                    conn.close();
                    conn = null;
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    /**
     * 
     * @param item
     *
    public void postBlogItem(BlogEntry item) throws IOException {
    HttpConnection con = null;
    try {
    con = (HttpConnection) Connector.open(endpoint + blogthispost);
    con.setRequestMethod(HttpConnection.POST);
    con.setRequestProperty("User-Agent", Constants.USER_AGENT);
    OutputStream output = con.openOutputStream();
    
    output.write(("ID=" + item.getAbout().getId()).getBytes());
    output.write(("&Author=" + item.getAuthor()).getBytes());
    output.write(("&Text=" + item.getText()).getBytes());
    if (item.getImage() != null) {
    byte[] imageData = item.getImage();
    String encodedData = String.valueOf(imageData);//Base64.encode(imageData, 0, imageData.length);
    output.write("&Image=".getBytes());
    output.write(encodedData.getBytes());
    }
    output.flush();
    
    int rc = con.getResponseCode();
    if (rc != HttpConnection.HTTP_OK) {
    throw new IOException("HTTP response code: " + rc);
    }
    } finally {
    if (con != null) {
    con.close();
    }
    }
    }
     */
    private void addStandardServices(AbstractObject object, Vector services) {
        Service service = new Service(object);
        service.setName("Bookmark");
        service.setDescription("Add object to bookmarks");
        service.setUrl("bookmark://");
        services.addElement(service);

        if (object.getType() == ObjectType.LOCATION) {
            service = new Service(object);
            service.setName("Map");
            service.setDescription("Show location on map");
            service.setUrl("location://");
            services.addElement(service);
        }
        if (object.getType() == ObjectType.BARCODE) {
            if (object.getId().startsWith("http:") || object.getId().startsWith("https:")) {
                service = new Service(object);
                service.setUrl(object.getId());
                service.setName("Open URL");
                service.setDescription("Open this url in your browser");
            }
        }
        if (object.getType() == ObjectType.TAG) {
            TagObject tagObject = (TagObject) object;
            if (tagObject.getUri() != null) {
                service = new Service(tagObject);
                service.setUrl(tagObject.getUri());
                if (tagObject.getUri().startsWith("sms:")) {
                    service.setName("Send sms");
                    service.setDescription("Send an sms to");
                } else {
                    service.setName("Open URL");
                    service.setDescription("Open this url in your browser");
                }
                services.insertElementAt(service, 0);
            }
        }
    }

    /*
     * Checks if given string is an URL.
     */
    private boolean isUrl(String pattern) {
        if (pattern.startsWith("http://") || pattern.startsWith("https://")) {
            return true;
        }
        return false;
    }
}
